#pragma once
#include <sys/epoll.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include <sys/uio.h>
#include "locker.h"


class http_conn
{
public:
    //有限状态机
    enum CHECK_STATE{CHECK_STATE_REQUESTLINE=0,CHECK_STATE_HEADER,CHECK_STATE_CONTENT};
    enum LINE_STATUS{LINE_OK=0,LINE_BAD,LINE_OPEN};
    enum HTTP_CODE{NO_REQUEST,GET_REQUEST,BAD_REQUEST,NO_RESOURCE,FORBIDDEN_REQUEST,FILE_REQUEST,
    
    INTERNAL_ERROR,
    CLOSED_CONNECTION
    };

    enum METHOD {GET=0,POST,HEAD,PUT,DELETE,TRACE,OPTIONS,CONNECT,PATCH};
    static int m_epfd;//所有socket上的事件都被注册到同一个epfd
    static int m_user_count;//统计用户的数量
    static const int READ_BUF_SIZE=2048;//读缓冲区的大小
    static const int WRITE_BUF_SIZE=2048;//写缓冲区的大小
    static const int FILENAME_LEN=200;

    http_conn(){}

    ~http_conn(){}
    bool read();  //非阻塞读
    bool write(); //非阻塞写

    void unmap();


    void process();//处理客户端请求
    void init(int sockfd,const sockaddr_in &addr);
    //关闭连接
    void close_conn();
    //解析http请求
    HTTP_CODE process_read();

    //解析请求首航
    HTTP_CODE parse_request_line(char*text);
    //解析请求头
     HTTP_CODE parse_headers(char*text);
    
     //解析请求体
      HTTP_CODE parse_content(char*text);

      LINE_STATUS parse_line();

      bool  process_write(HTTP_CODE ret);
      bool add_response(const char*format,...);
      bool add_content(const char*content);
      bool add_status_line(int status,const char*title);
      bool add_headers(int content_length);
      bool add_linger();
      bool add_blank_line();
      bool add_content_length(int content_len);

      
private:

    char*m_url;//目标的url
    char*m_version;//协议版本
    METHOD m_method;
    char*m_host;
    bool m_linger;//判断http请求，判断连接
    //http请求的长度
    int m_content_length;
    char m_real_file[FILENAME_LEN];

    struct stat m_file_stat;

    char*m_file_address;





private:
    int m_checked_index;//当前正在分析的字符在文件缓冲区的位置
    int m_start_line;//当前正在解析的行的起始位置

    CHECK_STATE m_check_state;//主状态机当前所处状态

    void init();//初始化连接其余的信息

    int m_sockfd;//这个http连接的socket
    sockaddr_in m_addr;//通信的socket地址

    char m_read_buf[READ_BUF_SIZE];//请求体数据
    int m_read_idx;
    char m_write_buf[WRITE_BUF_SIZE];

    char*get_line(){return m_read_buf+m_start_line;}//获取一行数据

    HTTP_CODE do_request();

    struct iovec m_iv[2];
    int m_iv_count;
    int m_write_idx=0;

};